package com.atguigu.tingshu.album.service.impl;

import com.alibaba.csp.sentinel.util.AssertUtil;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.base.BaseEntity;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumTrackListVo;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private VodService vodService;
    @Autowired
    private AlbumInfoService albumInfoService;
    @Autowired
    private TrackStatMapper trackStatMapper;
    @Qualifier("com.atguigu.tingshu.user.client.UserInfoFeignClient")
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Qualifier("com.atguigu.tingshu.album.client.AlbumInfoFeignClient")
    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;


    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        Assert.notNull(trackInfo, "声音信息为空");
        Long albumId = trackInfo.getAlbumId();
        List<TrackInfo> trackInfos = trackInfoMapper.selectList(new LambdaQueryWrapper<TrackInfo>().eq(TrackInfo::getAlbumId, albumId));
        List<Long> trackIdList = trackInfos.stream()
                .filter(trackInfo1 -> trackInfo1.getOrderNum() > trackInfo.getOrderNum())
                .map(TrackInfo::getId)
                .collect(Collectors.toList());
        Result<List<Long>> listResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
        Assert.notNull(listResult, "用户付费信息集为空");
        List<Long> trackIdNoReaptList = listResult.getData();
        Assert.notNull(trackIdNoReaptList, "用户付费信息集为空");
        Result<AlbumInfo>  albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
        Assert.notNull(albumInfoResult, "专辑信息集为空");
        AlbumInfo albumInfo = albumInfoResult.getData();
        Assert.notNull(albumInfo, "专辑信息为空");

        // 构造声音分集购买数据列表
        List<Map<String, Object>> list = new ArrayList<>();


        if(trackIdNoReaptList.size() >= 0) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "本集");
            map.put("price", albumInfo.getPrice());
            map.put("trackCount", 0);
            list.add(map);
        }

        //后10集
        if(trackIdNoReaptList.size() > 0 && trackIdNoReaptList.size() <= 10) {
            Map<String, Object> map = new HashMap<>();
            int count = trackIdNoReaptList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后"+trackIdNoReaptList.size()+"集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        // 19
        if(trackIdNoReaptList.size() > 10) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(10));
            map.put("name", "后10集");
            map.put("price", price);
            map.put("trackCount", 10);
            list.add(map);
        }
        // 后20集
        if(trackIdNoReaptList.size() > 10 && trackIdNoReaptList.size() <= 20) {
            Map<String, Object> map = new HashMap<>();
            int count = trackIdNoReaptList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后"+count+"集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        if(trackIdNoReaptList.size() > 20) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(20));
            map.put("name", "后20集");
            map.put("price", price);
            map.put("trackCount", 20);
            list.add(map);
        }

        //后30集
        if(trackIdNoReaptList.size() > 20 && trackIdNoReaptList.size() <= 30) {
            Map<String, Object> map = new HashMap<>();
            int count = trackIdNoReaptList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后"+count+"集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        if(trackIdNoReaptList.size() > 30) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(30));
            map.put("name", "后30集");
            map.put("price", price);
            map.put("trackCount", 30);
            list.add(map);
        }

        //后50集
        if(trackIdNoReaptList.size() > 30 && trackIdNoReaptList.size() <= 50) {
            Map<String, Object> map = new HashMap<>();
            int count = trackIdNoReaptList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后"+count+"集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        // 最多购买50集;
        if(trackIdNoReaptList.size() > 50) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(50));
            map.put("name", "后50集");
            map.put("price", price);
            map.put("trackCount", 50);
            list.add(map);
        }
        return list;
    }

    @Override
    public void updateStat(Long albumId, Long trackId, String statType, Integer count) {
        trackInfoMapper.updateStat(trackId, statType, count);
        //	更新专辑播放量
        if (statType.equals(SystemConstant.TRACK_STAT_PLAY)) {
            albumInfoService.updateStat(albumId, SystemConstant.ALBUM_STAT_PLAY, count);
        }
    }

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> pageParam, Long albumId, Long userId) {
        IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.findAlbumTrackPage(pageParam, albumId, userId);
        AssertUtil.notNull(pageInfo.getRecords(), "声音信息为空");
        List<AlbumTrackListVo> AlbumTrackListVoList = pageInfo.getRecords();
        //获取是否为vip
        Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
        AssertUtil.notNull(userInfoVoResult, "用户信息集为空");
        UserInfoVo userInfoVo = userInfoVoResult.getData();
        AssertUtil.notNull(userInfoVo, "用户信息为空");
        Integer isVip = userInfoVo.getIsVip();
        //获取免费试听集数
        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
        AssertUtil.notNull(albumInfoResult, "专辑信息集为空");
        AlbumInfo albumInfo = albumInfoResult.getData();
        AssertUtil.notNull(albumInfo, "专辑信息为空");
        Integer tracksForFree = albumInfo.getTracksForFree();


        if (userId == null) {
            AlbumTrackListVoList.stream()
                    .filter(albumTracks -> albumTracks.getOrderNum() > tracksForFree)
                    .collect(Collectors.toList()).forEach(albumTrackListVo -> {
                        albumTrackListVo.setIsShowPaidMark(true);
                    });


        } else {
            Boolean isPay = false;
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                if (isVip == 0) {
                    isPay = true;
                }
                if (isVip == 1 && userInfoVo.getVipExpireTime().before(new Date())) {
                    isPay = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                isPay = true;
            }
            if (isPay) {
                List<Long> trackIdList = AlbumTrackListVoList.stream()
                        .filter(albumTracks -> albumTracks.getOrderNum() > tracksForFree)
                        .map(AlbumTrackListVo::getTrackId)
                        .collect(Collectors.toList());
                if (trackIdList.size() > 0) {
                    Result<List<Long>> trackIdList1 = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
                    if (trackIdList1.getData().size() > 0) {
                        AlbumTrackListVoList.forEach(albumTrackListVo -> {
                            if (trackIdList1.getData().contains(albumTrackListVo.getTrackId())) {
                                albumTrackListVo.setIsShowPaidMark(false);
                            } else {
                                albumTrackListVo.setIsShowPaidMark(true);
                            }
                        });
                    }
                }
            }

        }
        return null;
    }

    @Override
    public void removeTrackInfo(Long id) {
        TrackInfo trackInfo = this.getById(id);
        // 删除
        this.removeById(id);
        // 删除统计数据
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, id));
        // 更新专辑声音总数
        AlbumInfo albumInfo = this.albumInfoService.getById(trackInfo.getAlbumId());
        int includeTrackCount = albumInfo.getIncludeTrackCount() - 1;
        albumInfo.setIncludeTrackCount(includeTrackCount);
        albumInfoService.updateById(albumInfo);
        // 序号重新计算
        trackInfoMapper.updateTrackNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        //删除声音媒体
        vodService.removeTrack(trackInfo.getMediaFileId());
    }

    @Override
    public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
        //创建trackInfo对象
        TrackInfo trackInfo = new TrackInfo();
        trackInfo.setId(id);
        //获取mediafieldid
        String mediaFileId = trackInfo.getMediaFileId();
        //属性复制
        BeanUtils.copyProperties(trackInfo, trackInfoVo);

        if (!trackInfoVo.getMediaFileId().equals(mediaFileId)) {
            //根据mediafieldid查询媒体文件信息
            TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
            if (trackMediaInfoVo == null) {
                throw new GuiguException(ResultCodeEnum.VOD_FILE_ID_ERROR);
            }
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            trackInfo.setMediaType(trackMediaInfoVo.getType());

        }

        this.updateById(trackInfo);
    }

    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
        //调用mapper层方法

        return trackInfoMapper.findUserTrackPage(trackListVoPage, trackInfoQuery);
    }

    @Override
    @Transactional
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //新建trackInfo 对象
        TrackInfo trackInfo = new TrackInfo();
        //进行属性复制
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //获取上一条声音信息
        TrackInfo preTrackInfo = this.getOne(new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId())
                .orderByDesc(TrackInfo::getId)
                .select(TrackInfo::getOrderNum)
                .last(" limit 1 "));
        int orderNum = 1;
        if (null != preTrackInfo) {
            orderNum = preTrackInfo.getOrderNum() + 1;
        }
        trackInfo.setOrderNum(orderNum);
        //根据mediaID获取流媒体信息
        TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
        trackInfo.setMediaSize(trackMediaInfo.getSize());
        trackInfo.setMediaUrl(trackMediaInfo.getMediaUrl());
        trackInfo.setMediaDuration(trackMediaInfo.getDuration());
        trackInfo.setMediaType(trackMediaInfo.getType());
        trackInfo.setUserId(userId);
        trackInfoMapper.insert(trackInfo);

        //更新专辑总数
        AlbumInfo albumInfo = albumInfoService.getById(trackInfo.getAlbumId());
        albumInfoService.update(new LambdaUpdateWrapper<AlbumInfo>().set(AlbumInfo::getIncludeTrackCount, albumInfo.getIncludeTrackCount() + 1));

        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
    }

    private void saveTrackStat(Long trackId, String trackType) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(trackType);
        trackStat.setStatNum(0);
        this.trackStatMapper.insert(trackStat);
    }
}
